import { ref } from 'vue'
import type { UploadFile } from 'element-plus' // 引入文件类型
import type { PublishProductForm } from '@/types/product'

export default function () {
  const fileList = ref<UploadFile[]>([]) // 用于存储选择的文件
  const dialogMediaUrl = ref('') // 用于存储图片或视频预览的地址
  const acceptType = ref<string>('') // 用于限制上传文件的类型
  const dialogVisible = ref(false) // 用于控制图片或视频预览的显示与隐藏
  const isVideo = ref(false) // 用于判断是否为视频
  const fileLimit = ref<number>() // 限制最多选择 6 个文件
  // 判断是否存在图片文件
  const isExistImage = (fileList: UploadFile[]): boolean => {
    return fileList.some((file: UploadFile) => {
      return file.raw && file.raw.type.startsWith('image') //存在图片文件则返回 true,否则返回 false
    })
  }

  // 判断是否存在两种类型的文件
  const hasBothTypes = (fileList: UploadFile[]) => {
    let hasImage = false
    let hasVideo = false
    fileList.forEach(file => {
      if (file.raw) {
        if (file.raw.type.startsWith('image')) {
          hasImage = true
        } else if (file.raw.type.startsWith('video')) {
          hasVideo = true
        }
      }
    })
    return hasImage && hasVideo // 同时存在图片和视频则返回 true
  }

  // 处理文件列表的变化
  const handleChange = (file: UploadFile, newFileList: UploadFile[], publishForm: PublishProductForm) => {
    publishForm.image = '#' // 用于触发表单校验

    // 1. 判断是否同时选择了图片和视频
    if (hasBothTypes(newFileList)) {
      ElMessage({
        type: 'error',
        message: '不能同时选择图片和视频文件',
      })
      return
    }
    const isImage = isExistImage(newFileList)

    // 2. 处理图片文件
    if (isImage) {
      acceptType.value = 'image/*' // 限制只能选择图片
      fileLimit.value = 6
      if (newFileList.length > 6) {
        ElMessage({
          type: 'error',
          message: '最多只能选择 6 张照片',
        })
        return
      }

      if (fileList.value.length === 0 || isExistImage(fileList.value)) {
        fileList.value = newFileList // 直接赋值
      } else {
        ElMessage({
          type: 'error',
          message: '已经选择图片，不能选择视频文件',
        })
      }
    }
    // 3. 处理视频文件
    else {
      acceptType.value = 'video/*' // 限制只能选择视频
      fileLimit.value = 1
      if (fileList.value.length === 0 && newFileList.length === 1) {
        // 生成视频缩略图
        generateVideoThumbnail(file.raw!).then(thumbnailUrl => {
          file.url = thumbnailUrl
          fileList.value = newFileList // 更新文件列表
        })
      }
    }
  }

  // 处理删除文件
  const handleRemove = (file: UploadFile, newFileList: UploadFile[], publishForm: PublishProductForm) => {
    if (newFileList.length === 0) {
      publishForm.image = '' // 清空图片地址
      acceptType.value = '' // 清空文件类型限制
      dialogMediaUrl.value = '' // 清空图片或视频预览地址
      dialogVisible.value = false // 隐藏图片或视频预览
    }
    fileList.value = newFileList // 更新文件列表
  }

  // 处理超过最大选择数的情况
  const handleExceed = () => {
    ElMessage({
      type: 'error',
      message: '文件个数超出最大限制',
    })
  }

  // 图片或视频预览
  const handlePictureCardPreview = (file: UploadFile) => {
    if (file.raw && file.raw.type.startsWith('video')) {
      dialogMediaUrl.value = URL.createObjectURL(file.raw)
    } else {
      dialogMediaUrl.value = file.url!
    }
    // 判断是否为视频,如果是则显示视频播放器
    isVideo.value = file.raw ? file.raw.type.startsWith('video') : false
    dialogVisible.value = true
  }

  // 生成视频缩略图
  const generateVideoThumbnail = (file: File): Promise<string> => {
    return new Promise((resolve, reject) => {
      const video = document.createElement('video')
      const canvas = document.createElement('canvas')
      const context = canvas.getContext('2d')

      video.preload = 'metadata'
      video.src = URL.createObjectURL(file)
      video.onloadeddata = () => {
        video.currentTime = 1
      }
      video.onseeked = () => {
        canvas.width = video.videoWidth
        canvas.height = video.videoHeight
        context?.drawImage(video, 0, 0, canvas.width, canvas.height)
        URL.revokeObjectURL(video.src)
        resolve(canvas.toDataURL('image/png'))
      }
      video.onerror = error => {
        reject(error)
      }
    })
  }

  return {
    fileList,
    dialogMediaUrl,
    dialogVisible,
    isVideo,
    fileLimit,
    acceptType,
    handleChange,
    handleRemove,
    handleExceed,
    handlePictureCardPreview,
  }
}
